package org.jsola.hr.web;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jsola.cache.ICache;
import org.jsola.core.Result;
import org.jsola.exception.JsolaException;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.CacheKeyKit;
import org.jsola.hr.constant.EmpInfoScene;
import org.jsola.hr.constant.EmpInfoStatus;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dto.*;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.provider.IHrEmpInfoRelationService;
import org.jsola.hr.query.DepInfoQuery;
import org.jsola.hr.query.PositionInfoQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.message.service.ISmsSendService;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;

/**
 * @author JanusMix
 */
@Slf4j
@RestController("hrEmpInfoRelationController")
@RequestMapping(HrConstants.API_PATH + "/v1/hrEmpInfoRelation")
public class HrEmpInfoRelationController implements IHrEmpInfoRelationControllerAPI {

    @Autowired
    private IHrEmpInfoRelationService hrEmpInfoRelationService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpWorkService empWorkService;

    @Autowired
    private IEmpEducationService empEducationService;

    @Autowired
    private ICache cache;

    @Autowired
    private ICompanyEmpInfoRequireService companyEmpInfoRequireService;

    @Autowired
    private IDepInfoService depInfoService;

    @Autowired
    private IPositionInfoService positionInfoService;

    @Autowired
    private ISmsSendService sendShortMessage;

    @Override
    @PostMapping(value = "hrSendShortMessage")
    public Result<Boolean> hrSendShortMessage(@RequestBody String phone) {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String host = request.getServerName();
        log.info("hr project: sendCode add domain, host:{}",host);
        return Result.success(
//                hrEmpInfoRelationService.hrSendShortMessage(phone)
                hrEmpInfoRelationService.hrSendShortMessage(phone, host)
        );
    }

    @Override
    @PostMapping(value = "hrSendShortMessageByDeviceType")
    public Result<Boolean> hrSendShortMessageByDeviceType(@RequestBody String phone) {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String deviceType = request.getHeader("devicetype");
        log.info("hr project: sendCode add devicetype, devicetype:{}",deviceType);
        return Result.success(
                hrEmpInfoRelationService.hrSendShortMessageByDeviceType(phone, deviceType)
        );
    }


    @Override
    @PostMapping(value = "hrVerificationCodeLogin")
    public Result<EmpAllInfoVO> hrVerificationCodeLogin(@RequestBody PhoneVerificationCodeDTO phoneVerificationCodeDTO) {
        return Result.success(
                hrEmpInfoRelationService.verificationCodeLogin(phoneVerificationCodeDTO)
        );
    }

    @Override
    @PostMapping(value = "hrVerificationCodeLoginWeChat")
    public Result<EmpLoginResultVO> hrVerificationCodeLoginWeChat(@RequestBody PhoneVerificationCodeDTO phoneVerificationCodeDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes)
                    Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String host = request.getServerName();
            phoneVerificationCodeDTO.setHost(host);
            return Result.success(hrEmpInfoRelationService.verificationCodeLoginWeChat(phoneVerificationCodeDTO));
        } catch (JsolaException je) {
            return Result.fail(je.getMessage());
        }
    }

    @Override
    @PostMapping(value = "hrVerificationCodeLoginWeChatByDevicetype")
    public Result<EmpLoginResultVO> hrVerificationCodeLoginWeChatByDevicetype(@RequestBody PhoneVerificationCodeDTO phoneVerificationCodeDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String deviceType = request.getHeader("devicetype");
            phoneVerificationCodeDTO.setDeviceType(deviceType);
            return Result.success(hrEmpInfoRelationService.verificationCodeLoginWeChatByDevicetype(phoneVerificationCodeDTO));
        } catch (JsolaException je) {
            return Result.fail(je.getMessage());
        }
    }
    
    @Override
    @PostMapping(value = "hrVerificationCodeLoginWeChatForAdmin")
    public Result<EmpLoginResultVO> hrVerificationCodeLoginWeChatForAdmin(PhoneVerificationCodeDTO phoneVerificationCodeDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes)
                    Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String host = request.getServerName();
            phoneVerificationCodeDTO.setHost(host);
            return Result.success(hrEmpInfoRelationService.verificationCodeLoginWeChatForAdmin(phoneVerificationCodeDTO));
        } catch (JsolaException je) {
            return Result.fail(je.getMessage());
        }
    }

    @Override
    @PostMapping(value = "hrVerificationCodeLoginWeChatByDevicetypeNoLogic")
    public Result<String> hrVerificationCodeLoginWeChatByDevicetypeNoLogic(@RequestBody PhoneVerificationCodeDTO phoneVerificationCodeDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String deviceType = request.getHeader("devicetype");
            phoneVerificationCodeDTO.setDeviceType(deviceType);
            return Result.success(hrEmpInfoRelationService.verificationCodeLoginWeChatByDevicetypeNoLogic(phoneVerificationCodeDTO));
        } catch (JsolaException je) {
            return Result.fail(je.getMessage());
        }
    }

    @Override
    @PostMapping(value = "hrVerificationCodeOfficialAccount")
    public Result<Boolean> hrVerificationCodeOfficialAccount(@RequestBody PhoneVerificationCodeDTO phoneVerificationCodeDTO) {
        try {
            return Result.success(hrEmpInfoRelationService.hrVerificationCodeOfficialAccount(phoneVerificationCodeDTO));
        } catch (JsolaException je) {
            return Result.fail(je.getMessage());
        }
    }

    @Override
    @PostMapping(value = "checkPhoneBind")
    public Result<Boolean> checkPhoneBind(@Valid @RequestBody WeChatBindFromOffAccountDTO weChatBindFromOffAccountDTO) {

        return Result.success(
                hrEmpInfoRelationService.checkPhoneBind(weChatBindFromOffAccountDTO)
        );
    }

    @Override
    @GetMapping(value = "/empInfoRequire/{ticket}")
    public Result<CompanyEmpAllInfoRequireVO> findEmpInfoRequire(@PathVariable String ticket) {

        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);

        String companyId = empInfoLogin.getCompanyId();

        // todo 查看公司员工所需信息权限校验
        // 场景,入职
        String type = EmpInfoScene.ENTRY.getValue();

        return Result.success(
                companyEmpInfoRequireService.findByCompanyId(companyId, type, tokenUser)
        );
    }

    /**
     * 根据ticket获取登录的人员信息
     *
     * @param ticket ticket
     * @return 人员信息
     */
    private EmpInfoVO getEmpInfoByTicket(String ticket, TokenUser tokenUser) {

        Object obj = cache.get(CacheKeyKit.getTicketCacheKey(ticket));
        if (Objects.isNull(obj)) {
            throw new JsolaException("未登录或已过期");
        }
        log.info("ticket:{},value:{}", ticket, obj);
        EmpAllInfoVO empAllInfoVOTmp = JSON.parseObject(obj.toString(), EmpAllInfoVO.class);
        if (Objects.isNull(empAllInfoVOTmp)) {
            throw new JsolaException("ticket不正确");
        }
        tokenUser.setSiteId(empAllInfoVOTmp.getSiteId());
        tokenUser.setUserId("h5");

        EmpInfoVO empInfoCheck = empInfoService.selectById(empAllInfoVOTmp.getId(), tokenUser.getSiteId());
        if (Objects.isNull(empInfoCheck)) {
            if (StringUtils.isEmpty(empAllInfoVOTmp.getUnionId())) {
                throw new JsolaException("用户信息不存在或已删除");
            }
            List<EmpInfoListVO> empInfoList = empInfoService.listByUnionId(empAllInfoVOTmp.getUnionId(), EmpInfoStatus.WAIT_ENTRY.getValue());
            if (CollectionUtils.isEmpty(empInfoList)) {
                throw new JsolaException("根据unionId获取用户信息不存在");
            } else if (empInfoList.size() > 1) {
                throw new JsolaException("用户在多个租户下存在待入职信息,请检查");
            }
            EmpInfoListVO empInfoListVO = empInfoList.get(0);
            empAllInfoVOTmp.setId(empInfoListVO.getId());
            empAllInfoVOTmp.setSiteId(empInfoListVO.getSiteId());
            empAllInfoVOTmp.setCompanyId(empInfoListVO.getCompanyId());

            tokenUser.setSiteId(empInfoListVO.getSiteId());
        } else {
            empAllInfoVOTmp.setCompanyId(empInfoCheck.getCompanyId());
        }
        log.info("根据ticket获取用户信息,ticket:{},tokenUser:{},empInfo:{}", ticket, tokenUser, empAllInfoVOTmp);
        return empAllInfoVOTmp;
    }


    @Override
    @GetMapping(value = "/listAllDepInfo/{ticket}")
    public Result<List<DepInfoListVO>> listAllDepInfo(@PathVariable String ticket) {
        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);
        String companyId = empInfoLogin.getCompanyId();
        // todo 查看部门信息权限校验

        DepInfoQuery depInfoQuery = new DepInfoQuery();
        depInfoQuery.setCompanyId(companyId);

        return Result.success(
                depInfoService.select(depInfoQuery, tokenUser.getSiteId())
        );
    }


    @Override
    @GetMapping(value = "/listTreeDepInfo/{ticket}")
    public Result<List<DepInfoListVO>> listTreeDepInfo(@PathVariable String ticket) {
        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);
        String companyId = empInfoLogin.getCompanyId();
        // todo 查看部门信息权限校验

        DepInfoQuery depInfoQuery = new DepInfoQuery();
        depInfoQuery.setCompanyId(companyId);

        return Result.success(
                depInfoService.listTree(depInfoQuery, tokenUser.getSiteId())
        );
    }

    @Override
    @GetMapping(value = "/listAllPositionInfo/{ticket}")
    public Result<List<PositionInfoListVO>> listAllPositionInfo(@PathVariable String ticket) {
        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);
        String companyId = empInfoLogin.getCompanyId();
        // todo 查看岗位信息权限校验

        PositionInfoQuery positionInfoQuery = new PositionInfoQuery();
        positionInfoQuery.setCompanyId(companyId);

        return Result.success(
                positionInfoService.select(positionInfoQuery, tokenUser.getSiteId())
        );
    }

    @Override
    @GetMapping(value = "/listTreePositionInfo/{ticket}")
    public Result<List<PositionInfoListVO>> listTreePositionInfo(@PathVariable String ticket) {
        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);
        String companyId = empInfoLogin.getCompanyId();
        // todo 查看部门信息权限校验
        PositionInfoQuery positionInfoQuery = new PositionInfoQuery();
        positionInfoQuery.setCompanyId(companyId);

        return Result.success(
                positionInfoService.listTree(positionInfoQuery, tokenUser)
        );
    }

    @Override
    @PostMapping(value = "/saveWork/{ticket}")
    public Result<EmpWorkVO> saveWork(@PathVariable String ticket,
                                      @Valid @RequestBody EmpWorkAddDTO empWorkAddDTO) {
        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);
        empWorkAddDTO.setCompanyId(empInfoLogin.getCompanyId());
        empWorkAddDTO.setEmpId(empInfoLogin.getId());
        // todo 新增员工工作经历权限校验

        return Result.success(
                empWorkService.save(empWorkAddDTO, tokenUser)
        );
    }


    @Override
    @PutMapping(value = "/updateWork/{ticket}")
    public Result<Integer> updateWork(@PathVariable String ticket,
                                      @Valid @RequestBody EmpWorkUpdateDTO empWorkUpdateDTO) {
        TokenUser tokenUser = new TokenUser();
        getEmpInfoByTicket(ticket, tokenUser);
        // todo 修改员工工作经历权限校验

        int count = empWorkService.update(empWorkUpdateDTO, tokenUser);
        if (count == 0) {
            throw new ParamException("更新失败，请刷新页面后重试");
        }
        return Result.success(count);
    }


    @Override
    @DeleteMapping(value = "/work/{ticket}/{empWorkId}")
    public Result<Integer> deleteWork(@PathVariable String ticket,
                                      @PathVariable String empWorkId) {
        TokenUser tokenUser = new TokenUser();
        getEmpInfoByTicket(ticket, tokenUser);
        // todo 彻底删除员工工作经历权限校验

        int count = empWorkService.deleteByIds(tokenUser, empWorkId);
        if (count == 0) {
            throw new ParamException("删除失败，请刷新页面后重试");
        }
        return Result.success(count);
    }

    @Override
    @PostMapping(value = "/saveEducation/{ticket}")
    public Result<EmpEducationVO> saveEducation(@PathVariable String ticket,
                                                @Valid @RequestBody EmpEducationAddDTO empEducationAddDTO) {
        TokenUser tokenUser = new TokenUser();
        EmpInfoVO empInfoLogin = getEmpInfoByTicket(ticket, tokenUser);
        empEducationAddDTO.setCompanyId(empInfoLogin.getCompanyId());
        empEducationAddDTO.setEmpId(empInfoLogin.getId());
        // todo 新增员工教育经历权限校验

        return Result.success(
                empEducationService.save(empEducationAddDTO, tokenUser)
        );
    }


    @Override
    @PutMapping(value = "/updateEducation/{ticket}")
    public Result<Integer> updateEducation(@PathVariable String ticket,
                                           @Valid @RequestBody EmpEducationUpdateDTO empEducationUpdateDTO) {
        TokenUser tokenUser = new TokenUser();
        getEmpInfoByTicket(ticket, tokenUser);
        // todo 修改员工教育经历权限校验

        int count = empEducationService.update(empEducationUpdateDTO, tokenUser);
        if (count == 0) {
            throw new ParamException("更新失败，请刷新页面后重试");
        }
        return Result.success(count);
    }


    @Override
    @DeleteMapping(value = "/education/{ticket}/{empEducationId}")
    public Result<Integer> deleteEducation(@PathVariable String ticket,
                                           @PathVariable String empEducationId) {
        TokenUser tokenUser = new TokenUser();
        getEmpInfoByTicket(ticket, tokenUser);
        // todo 彻底删除员工教育经历权限校验

        int count = empEducationService.deleteByIds(tokenUser, empEducationId);
        if (count == 0) {
            throw new ParamException("删除失败，请刷新页面后重试");
        }
        return Result.success(count);
    }

    @Override
    @PutMapping(value = "/updateEmpAllInfo/{ticket}")
    public Result<Integer> updateEmpAllInfo(@PathVariable String ticket,
                                            @Valid @RequestBody EmpAllInfoDTO empAllInfoDTO) {
        TokenUser tokenUser = new TokenUser();
        getEmpInfoByTicket(ticket, tokenUser);
        // todo 修改员工信息权限校验

        EmpInfoDO empInfoDO = empInfoService.selectDOById(empAllInfoDTO.getId(), tokenUser.getSiteId());
        if (Objects.isNull(empInfoDO)) {
            return Result.fail("员工信息不正确");
        }
        Result result = checkEmpNumberAndPhone(empInfoDO.getId(), empInfoDO.getCompanyId(), empAllInfoDTO.getPhone(), empAllInfoDTO.getNumber(), tokenUser);
        if (!result.getSuccess()) {
            return Result.fail(result.getMsg());
        }

        empAllInfoDTO.setJoinFormStatus(true);
        int count = empInfoService.updateEmpAllInfo(empAllInfoDTO, tokenUser);
        if (count == 0) {
            throw new ParamException("更新失败，请刷新页面后重试");
        }
        return Result.success(count);
    }

    /**
     * 校验用户信息手机号和工号
     *
     * @param id        id
     * @param companyId 公司id
     * @param phone     手机号
     * @param number    工号
     * @param tokenUser 当前用户
     * @return 校验结果
     */
    private Result checkEmpNumberAndPhone(String id, String companyId, String phone, String number, TokenUser tokenUser) {
        if (!StringUtils.isEmpty(phone)) {
            EmpInfoVO empInfoVO = empInfoService.selectByPhone(companyId, phone, tokenUser.getSiteId());
            if (!Objects.isNull(empInfoVO)) {
                if (!id.equals(empInfoVO.getId())) {
                    return Result.fail("手机号" + phone + "已被使用,请修改!");
                }
            }
        }
        if (!StringUtils.isEmpty(number)) {
            EmpInfoVO empInfoVO = empInfoService.selectByNumber(companyId, number, tokenUser.getSiteId());
            if (!Objects.isNull(empInfoVO)) {
                if (!id.equals(empInfoVO.getId())) {
                    return Result.fail("工号" + number + "已被使用,请修改!");
                }
            }
        }
        return Result.success();
    }
}
